#ifndef USERSETTINGS_H
#define USERSETTINGS_H
#include "libs/base/basetype.h"
#include "libs/core/user/loginuser.h"
#include "services/serviceurls.h"
#include <QDir>
#include <QJsonObject>
#include <QRect>

struct RecorderSettings
{
    QString video_save_dir;
    int realtime_monitor_count = 0;
    int realtime_monitor_frequency = 1; // seconds
    int regular_monitor_count = 3;
    int regular_monitor_frequency = 1; // minutes
    int recorder_count = 5;

    QJsonObject toJSONObject() const
    {
        return QJsonObject { { "videoSaveDir", video_save_dir },
                             { "realtimeMonitorCount", realtime_monitor_count },
                             { "realtimeMonitorFrequency", realtime_monitor_frequency },
                             { "regularMonitorCount", regular_monitor_count },
                             { "regularMonitorFrequency", regular_monitor_frequency },
                             { "recorderCount", recorder_count } };
    }

    static RecorderSettings fromJSONObject(const QJsonObject& jo)
    {
        return RecorderSettings {
            jo["videoSaveDir"].toString(),           jo["realtimeMonitorCount"].toInt(0),
            jo["realtimeMonitorFrequency"].toInt(1), jo["regularMonitorCount"].toInt(2),
            jo["regularMonitorFrequency"].toInt(3),  jo["recorderCount"].toInt(3)
        };
    }
};

struct AudioSettings
{
    int sample_rate = 44100;
    int bitrate = 128000;
    int channels = 2;

    QJsonObject toJSONObject() const
    {
        return QJsonObject { { "sampleRate", sample_rate },
                             { "bitrate", bitrate },
                             { "channels", channels } };
    }

    static AudioSettings fromJSONObject(const QJsonObject& jo)
    {
        return AudioSettings { jo["sampleRate"].toInt(44100), jo["bitrate"].toInt(128000),
                               jo["channels"].toInt(2) };
    }
};

struct VideoSettings
{
    QString resolution = "original";
    int bitrate = 8000000;
    int frame_rate = 30;

    QJsonObject toJSONObject() const
    {
        return QJsonObject { { "resolution", resolution },
                             { "bitrate", bitrate },
                             { "frameRate", frame_rate } };
    }

    static VideoSettings fromJSONObject(const QJsonObject& jo)
    {
        return VideoSettings { jo["resolution"].toString("original"), jo["bitrate"].toInt(8000000),
                               jo["frameRate"].toInt(30) };
    }
};

struct ScreenCaptureSettings
{
    QString save_dir;
    int aspect_ratio_index = 1;
    AudioSettings audio;
    VideoSettings video;

    QJsonObject toJSONObject() const
    {
        return QJsonObject { { "saveDir", save_dir },
                             { "aspectRatioIndex", aspect_ratio_index },
                             { "audio", audio.toJSONObject() },
                             { "video", video.toJSONObject() } };
    }

    static ScreenCaptureSettings fromJSONObject(const QJsonObject& jo)
    {
        return ScreenCaptureSettings { jo["saveDir"].toString(), jo["aspectRatioIndex"].toInt(1),
                                       AudioSettings::fromJSONObject(jo["audio"].toObject()),
                                       VideoSettings::fromJSONObject(jo["video"].toObject()) };
    }
};

class UserSettings
{
public:
    static UserSettings& instance();

    ServiceUrls serviceUrls() const;
    const yc::LanguageScript& language() const { return language_; }

    bool disclaimerAccepted() const { return disclaimer_accepted_; }
    void setDisclaimerAccepted(bool shown) { disclaimer_accepted_ = shown; }

    const QString& upgradeUrl() const { return upgrade_url_; }
    QString ignoreMajorVersion() const { return ignore_major_version_; }
    void setIgnoreMajorVersion(const QString& version) { ignore_major_version_ = version; }
    QString ignoreUpdateDate() const { return ignore_update_date_; }
    void setIgnoreUpdateDate(const QString& date) { ignore_update_date_ = date; }
    int windowState() const { return window_state_; }
    void setWindowState(int state) { window_state_ = state; }
    const QRect& windowRect() const { return window_rect_; }
    void setWindowRect(const QRect& rect) { window_rect_ = rect; }

    // Dir
    const QDir& accessDir() const { return access_dir_; }
    void setAccessDir(const QDir& dir) { access_dir_ = dir; }
    const QDir& cacheDir() const { return cache_dir_; }
    const QDir& newCacheDir() const { return new_cache_dir_; }
    void setNewCacheDir(const QDir& dir) { new_cache_dir_ = dir; }
    QDir resDir();
    QDir tempDir();

    // Login user
    const yc::LoginUser& loginUser() const { return login_user_; }
    yc::LoginUser& loginUser() { return login_user_; }
    void setLoginUser(const yc::LoginUser& u) { login_user_ = u; }

    // Recorder
    const RecorderSettings& recorderSettings() const { return recorder_settings_; }
    const RecorderSettings& newRecorderSettings() const { return new_recorder_settings_; }
    void setNewRecorderSettings(const RecorderSettings& settings)
    {
        new_recorder_settings_ = settings;
    }

    // ScreenCapture
    const ScreenCaptureSettings& screenCaptureSettings() const { return screen_capture_settings_; }
    void setScreenCaptureSettings(const ScreenCaptureSettings& settings)
    {
        screen_capture_settings_ = settings;
    }

    bool webDebugEnabled() const { return web_debug_enabled_; }
    void setWebDebugEnabled(bool enabled) { web_debug_enabled_ = enabled; }

    void load();
    void save();

    static QDir rootDir();
    static QDir logDir();
    static QDir webCacheDir();

private:
    UserSettings();

    enum { VERSION_NUMBER = 4 };

    yc::EnvType env_ = yc::PROD_ENV_TYPE;
    yc::LanguageScript language_;
    bool disclaimer_accepted_ = false;
    QString upgrade_url_;
    QString ignore_major_version_;
    QString ignore_update_date_;
    int window_state_ = 0;
    QRect window_rect_;
    QDir cache_dir_;
    QDir new_cache_dir_;
    QDir access_dir_;
    yc::LoginUser login_user_;
    RecorderSettings recorder_settings_;
    RecorderSettings new_recorder_settings_;
    ScreenCaptureSettings screen_capture_settings_;
    bool web_debug_enabled_ = false;
};

#endif // USERSETTINGS_H
